#pragma once

using namespace System;
using namespace System::Runtime::InteropServices;

#define VPX_CODEC_DISABLE_COMPAT 1
#include<vpx\vpx_encoder.h>
#include<vpx\vp8cx.h>
#define encInterface (vpx_codec_vp8_cx())

#include"Image.h"
#include"Packet.h"
#include"Common.h"

namespace NVP8 
{
	public ref class Encoder
	{
	public:
		Encoder()
		{
			cfg = new vpx_codec_enc_cfg_t();
			codec = new vpx_codec_ctx_t();
			iter = new vpx_codec_iter_t();
		}

		void Init(int width, int height)
		{
			Init(width, height, 0);
		}
		
		void Init(int width, int height, int targetBitRate)
		{
			/* Populate encoder configuration */
			int res = vpx_codec_enc_config_default(encInterface, cfg, 0);
			if(res) 
			{
				throw gcnew InvalidOperationException("Failed to get config");
			}

			/* Update the default configuration with our settings */
			//cfg->rc_end_usage = VPX_VBR;
			if (targetBitRate != 0)
				cfg->rc_target_bitrate = targetBitRate;
			cfg->g_w = width;
			cfg->g_h = height;
			
			res = vpx_codec_enc_init(codec, encInterface, cfg, 0);
			ThrowOnError(res, codec, "Failed to initialize encoder");
		}

		bool Encode(VPXImage^ image, int timeStamp)
		{
			*iter = NULL;
			return vpx_codec_encode(codec, image->GetImageData(), timeStamp, 1, 0, VPX_DL_REALTIME) == VPX_CODEC_OK;
		}

		bool GetEncodedPacket(Packet^ packetData)
		{
            const vpx_codec_cx_pkt_t* pkt = vpx_codec_get_cx_data(codec, iter);
			if (pkt != NULL && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
			{
				packetData->Init(pkt);
				return true;
			}
			return false;
		}

		!Encoder()
		{
			vpx_codec_destroy(codec);
			delete cfg;
			delete codec;
			delete iter;
		}

		~Encoder()
		{
			this->!Encoder();
		}

	private:
		vpx_codec_ctx_t* codec;
		vpx_codec_enc_cfg_t* cfg;
		vpx_codec_iter_t* iter;
	};
}
